#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

using namespace EpollerModule;
using connection_t = std::shared_ptr<Connection>;

class Reactor
{
    const static int event_num = 64;

public:
    Reactor()
    {
        // 初始化数据
        _epoller = std::make_unique<Epoller>();
        _epoller->Init();
    }

    ~Reactor()
    {
    }

    void Loop()
    {
        _isrunning = true;

        while (_isrunning)
        {
            int timeout = -1;
            int n = _epoller->Wait(_revs, event_num, timeout);
            std::cout << "接收完毕，收到活跃个数为：" << n << std::endl;
            Dispenser(n);
        }

        _isrunning = false;
    }

    void InsertConnection(connection_t con)
    {
        // 1.加入管理
        _connections[con->GetSockfd()] = con;
        // 2.加入内核
        _epoller->Add(con->GetSockfd(), con->GetEvent());
        // 3.回指
        con->SetOwner(this);
    }

    void DeleteConnection(int fd)
    {
        _connections.erase(fd);
        _epoller->Delete(fd);
        close(fd);
    }

    void EnableReadWrite(int fd, bool read, bool write)
    {
        uint32_t events = (read ? EPOLLIN : 0) | (write ? EPOLLOUT : 0);
        _epoller->Update(fd, events);
    }

private:
    void Dispenser(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int fd = _revs[i].data.fd;
            if (IsExit(fd) && _revs[i].events & EPOLLIN)
            {
                _connections[fd]->Recver();
            }

            if (IsExit(fd) && _revs[i].events & EPOLLOUT)
            {
                _connections[fd]->Sender();
            }
        }
    }

    bool IsExit(int fd)
    {
        return _connections.count(fd);
    }

private:
    std::unique_ptr<Epoller> _epoller;
    std::unordered_map<int, connection_t> _connections; // fd: Connection， 服务器内部所有的连接
    bool _isrunning;
    struct epoll_event _revs[event_num];
};